# -*- mode: python; coding: utf-8 -*-

# Test if TwowayIter works

import unittest
import sys
sys.path.append("$basedir")

from ht import TwowayIter as TWI


def showExceptions(fn):
    def deco(*args, **kwargs):
        try: return fn(*args, **kwargs)
        except Exception, e:
            print >> sys.stderr, e
            raise
    deco.__doc__ = fn.__doc__
    return deco


class TWITest(unittest.TestCase):

    @showExceptions
    def test_need_indexable(self):
        """TwowayIter need an indexable object"""
        l = [1, 2, 3, 4]
        TWI(l)

        class Dummy: pass
        self.assertRaises(AssertionError, TWI, Dummy())

    @showExceptions
    def test_next(self):
        """TwowayIter can iter forwards"""
        l = [1, 2, 3, 4]
        i = TWI(l)

        # test all items
        self.assertTrue(i.next() == 1)
        self.assertTrue(i.next() == 2)
        self.assertTrue(i.next() == 3)
        self.assertTrue(i.next() == 4)

        self.assertRaises(StopIteration, i.next)
        self.assertRaises(StopIteration, i.next)

        # test last item
        i.prev()
        self.assertTrue(i.next() == 4)
        self.assertRaises(StopIteration, i.next)

    @showExceptions
    def test_prev(self):
        """TwowayIter can iter backwards"""
        l = [1, 2, 3, 4]
        i = TWI(l)

        # test firsts item
        self.assertRaises(StopIteration, i.prev)
        i.next()
        self.assertRaises(StopIteration, i.prev)
        i.next()
        self.assertTrue(i.prev() == 1)
        self.assertRaises(StopIteration, i.prev)

        # test last item
        i.next()
        i.next()
        i.next()
        self.assertRaises(StopIteration, i.next)

        # test others
        self.assertTrue(i.prev() == 3)
        self.assertTrue(i.prev() == 2)
        self.assertTrue(i.prev() == 1)

        self.assertRaises(StopIteration, i.prev)
        self.assertRaises(StopIteration, i.prev)

    @showExceptions
    def test_has_x(self):
        """Test if 'has_next' and 'has_prev' works"""
        l = [1, 2, 3, 4]
        i = TWI(l)

        # test first item
        self.assertFalse(i.has_prev)
        self.assertTrue(i.has_next)

        # test middle ones (only second item has prev)
        i.next()
        self.assertFalse(i.has_prev)
        self.assertTrue(i.has_next)

        i.next()
        self.assertTrue(i.has_prev)
        self.assertTrue(i.has_next)

        # test last item
        i.next()
        i.next()
        self.assertTrue(i.has_prev)
        self.assertFalse(i.has_next)

    @showExceptions
    def test_size(self):
        """Test if size works correctly"""
        l = [1, 2, 3, 4]
        i = TWI(l)

        self.assertTrue(len(l) == i.size)

    @showExceptions
    def test_index(self):
        """Test if index is updated correctly"""
        l = ['a', 'b', 'c', 'd']
        i = TWI(l)

        # Assure that index is updated every movement
        self.assertTrue(i.index == 0)
        i.next()
        self.assertTrue(i.index == 1)

        i.next()
        i.prev()
        self.assertTrue(i.index == 1)

        # 'index' is idempotent
        self.assertTrue(i.index == i.index)

        # # Assure that on StopIteration, index is not modified
        i.next()
        i.next()
        i.next()
        try: i.next()
        except StopIteration: pass

        self.assertTrue(i.index == 4)

        i.prev()
        i.prev()
        i.prev()
        try: i.prev()
        except StopIteration: pass

        self.assertTrue(i.index == 1)


UnitTestCase(TWITest)
